import Base2DPainter from "../Painter/Base2DPainter";
import CanvasException from "../Exception/CanvasException";
import Base3DPainter from "../Painter/Base3DPainter";
import Point3D from "../Point/Point3D";

export default class BaseCanvas {

    /**
     * @param id {string}
     * @param zIndex {number=}
     * @param painterType {Base2DPainter}
     */
    constructor({id, zIndex = 0, painterType = Base2DPainter}) {
        // default paintings
        this.paintings = [];
        // Get parent element id from document.
        let parentEle = document.getElementById(id);
        if (!parentEle) {
            throw new CanvasException({
                action: 'Create Canvas',
                message: 'Can not find the parent element.'
            })
        }
        // Init canvas
        this.canvasElm = document.createElement('canvas');
        this.drawnCanvas = document.createElement('canvas');

        this.drawnCanvas.width = this.canvasElm.width = this.width = parentEle.offsetWidth;
        this.drawnCanvas.height = this.canvasElm.height = this.height = parentEle.offsetHeight;
        this.drawnCanvas.style.cssText = this.canvasElm.style.cssText = 'position: absolute;top: 0;left:0;width: 100%;height: 100%;z-index:' + zIndex;

        this.ctx = this.drawnCanvas.getContext('2d');
        this.globalCtx = this.canvasElm.getContext('2d');
        // this.globalCtx = this.drawnCanvas.getContext('2d');
        // this.ctx = this.canvasElm.getContext('2d');
        // Init canvasContainer
        let canvasContainer = parentEle.getElementsByClassName('__canvas_container')[0];
        if (!canvasContainer) {
            canvasContainer = document.createElement('div');
            canvasContainer.className = '__canvas_container';
            canvasContainer.style.cssText = 'position: absolute;top: 0;left:0;width: 100%;height: 100%;';
            parentEle.appendChild(canvasContainer);
        }
        // Append canvas in last
        canvasContainer.appendChild(this.canvasElm);
        // Init painter
        if ((new painterType(this)) instanceof Base3DPainter) {
            this.eyePoint = new Point3D(this.width / 2, this.height / 2, 800);
        }
        this.painterType = painterType;
    }

    getPainter() {
        return new this.painterType(this);
    }

    /**
     * @param painting {BasePainting}
     */
    addPainting(painting) {
        // first
        painting.setCanvas(this);
        // second
        painting.setPainter(this.getPainter());
        this.paintings.push(painting);
    }

    drawAll() {
        this.clearCanvas();
        this.paintings.forEach((painting) => {
            painting.beDrawn.call(painting, painting.painter);
        });
        this.globalCtx.drawImage(this.drawnCanvas, 0, 0);
    }

    clearCanvas() {
        this.globalCtx.clearRect(0, 0, this.canvasElm.width, this.canvasElm.height);
        this.ctx.clearRect(0, 0, this.canvasElm.width, this.canvasElm.height);
    }

    activeDraggedScene() {
        let onSceneDragged = this.onSceneDragged.bind(this);
        window.addEventListener('mousedown', () => {
            window.addEventListener('mousemove', onSceneDragged);
        });
        window.addEventListener('mouseup', () => {
            window.removeEventListener('mousemove', onSceneDragged);
        });
        document.addEventListener('mousewheel', (e) => {
            this.eyePoint.z += e.wheelDeltaY/10;
        });
    }

    onSceneDragged(event) {
        this.eyePoint.x += event.movementX;
        this.eyePoint.y += event.movementY;
    }


}